package com.licode.codekit.buildprj;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.util.ResourceUtil;
import com.licode.codekit.utils.FileUtil;
import com.licode.codekit.utils.PomFile;
import com.licode.codekit.utils.StrUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @author licode
 */
public class ProjectCreator {
    public static final String PRJ_FILE = "project.zip";
    public static final String PRJ_POM = "pom.xml";
    public static final String STARTER_POM = "starter/pom.xml";
    public static final String MAIN_STARTER = "main-starter";
    public static final String MAIN_JAVA_FILE = "Application.java";
    public static final String MAIN_STARTER_POM = "starter/main-starter/pom.xml";
    public static final String JAVA_STARTER = "starter/main-starter/src/main/java";
    public static final String MAIN_APP_JAVA = "starter/main-starter/src/main/java/Application.java";

    public static final String CLIENT_ROOT = "client/src/main/java/";
    public static final String SERVICE_ROOT = "service/src/main/java/";

    public static final String SRC_ROOT = CodeKitConf.SRC_ROOT;
    public static final String MODULE_SRC_PREFIX = "module/";

    public static final String MODULES_NODE = "    </modules>";
    public static final String MODULE_TEMP = "        <module>{name}</module>\n" +
            "    </modules>";

    public ProjectCreator() {
    }

    private String getRootDir(String dir) {
        String zipRoot = dir;
        if (dir != null && dir.length() >= 2) {
            if (!dir.endsWith("/")) {
                zipRoot = dir + "/";
            }

            return zipRoot;
        } else {
            return "";
        }
    }

    public void createPrj(ProjectContext prjCtx) throws IOException {
        String rootDir = this.getRootDir(prjCtx.getRootDir());
        FileUtil.makeDirs(rootDir);

        prjCtx.setCurrentDir(rootDir);
        InputStream is = FileUtil.getResourceAsStream(PRJ_FILE);
        ZipInputStream inputStream = new ZipInputStream(is, StandardCharsets.UTF_8);

        for (ZipEntry nextEntry = inputStream.getNextEntry(); nextEntry != null; nextEntry = inputStream.getNextEntry()) {
            String name = nextEntry.getName();
            String pathName;

            name = name.replace("{module-name}", prjCtx.getModuleName())
                    .replace("{module-class-name}", prjCtx.getModuleClassName());

            if (nextEntry.isDirectory()) {
                pathName = name.replace(MAIN_STARTER, prjCtx.getArtifactId() + "-starter");
                FileUtil.makeDirs(rootDir + pathName);
            } else {
                String result = FileUtil.readText(inputStream, "utf-8");
                this.handlePrjFile(prjCtx, name, result);
            }

            inputStream.closeEntry();
        }

        inputStream.close();
    }

    public boolean createModule(Project rootPrj, ProjectContext prjCtx, String modelFile) throws IOException {
        int projectMode = 0;
        String rootDir = this.getRootDir(prjCtx.getRootDir()) + prjCtx.getModuleName() + "/";
        File file = new File(rootDir);

        if (file.exists() && file.isDirectory()) {
            Messages.showMessageDialog(rootPrj, "此模块已经存在！",
                    "温馨提示", Messages.getInformationIcon());
            return false;
        }

        prjCtx.setClientModule(prjCtx.getModuleName() + "-" + CodeKitConf.CLIENT_TAG);
        prjCtx.setServiceModule(prjCtx.getModuleName() + "-" + CodeKitConf.SERVICE_TAG);

        String midServicePkg = prjCtx.getGroupId().replace(".", "/");
        String midClientPkg = midServicePkg + "/" + CodeKitConf.CLIENT_TAG;

        prjCtx.setClientPackage(prjCtx.getGroupId() + "." + CodeKitConf.CLIENT_TAG);
        prjCtx.setServicePackage(prjCtx.getGroupId());

        if (prjCtx.getParentGroupId().equals(prjCtx.getServicePackage()) &&
            prjCtx.getParentArtifactId().equals(prjCtx.getArtifactId())) {
            Messages.showMessageDialog(rootPrj, "group-id和artifact-id不能和父模块相同！",
                    "温馨提示", Messages.getInformationIcon());
            return false;
        }

        prjCtx.setCurrentDir(rootDir);
        InputStream is = FileUtil.getResourceAsStream(modelFile);
        ZipInputStream inputStream = new ZipInputStream(is, StandardCharsets.UTF_8);

        midClientPkg += "/";
        midServicePkg += "/";

        file.mkdirs();

        for (ZipEntry nextEntry = inputStream.getNextEntry(); nextEntry != null; nextEntry = inputStream.getNextEntry()) {
            String name = nextEntry.getName();
            String pathName = "";
            int pos = name.lastIndexOf("/");
            String fileName = name.substring(pos + 1);
            String midDir = name.substring(0, pos + 1);
            projectMode = CodeKitConf.SERVICE_PRJ;

            if (name.startsWith(CLIENT_ROOT)) {
                projectMode = CodeKitConf.CLIENT_PRJ;
                pathName += prjCtx.getModuleName() + "-" + CLIENT_ROOT;
                pathName += midClientPkg + midDir.substring(CLIENT_ROOT.length());
            } else if (name.startsWith(SERVICE_ROOT)) {
                pathName = prjCtx.getModuleName() + "-" + SERVICE_ROOT;
                pathName += midServicePkg + midDir.substring(SERVICE_ROOT.length());
            } else if (name.startsWith(MODULE_SRC_PREFIX)) {
                pathName = midDir.substring(MODULE_SRC_PREFIX.length());
                if (pathName.startsWith(CodeKitConf.SRC_ROOT_PREFIX)) {
                    pathName = SRC_ROOT + midServicePkg + pathName.substring(SRC_ROOT.length());
                }
            } else {
                if (name.startsWith(CodeKitConf.CLIENT_PREFIX)) {
                    projectMode = CodeKitConf.CLIENT_PRJ;
                    pathName = prjCtx.getModuleName() + "-";
                } else if (name.startsWith(CodeKitConf.SERVICE_PREFIX)) {
                    pathName = prjCtx.getModuleName() + "-";
                }
                pathName += midDir;
            }

            if (fileName.startsWith(CodeKitConf.MODULE_CLASS_PREFIX)) {
                fileName = prjCtx.getModuleClassName()
                        + fileName.substring(CodeKitConf.MODULE_CLASS_PREFIX.length());
            }

            FileUtil.makeDirs(rootDir + pathName);

            if (!nextEntry.isDirectory()) {
                /**
                 * 最终生成的文件名称
                 */
                String filePath = rootDir + pathName + fileName;
                String result = FileUtil.readText(inputStream, "utf-8");
                FileUtil.saveStrToFile(filePath, prjCtx.handleContent(result, projectMode)
                        .getBytes(StandardCharsets.UTF_8));
                handlePomFile(filePath);
            }

            inputStream.closeEntry();
        }

        inputStream.close();

        // 写入自己的模块到模块列表
        prjCtx.addModule(prjCtx.getModuleName());
        prjCtx.updatePomFile();

        return true;
    }

    private void handlePomFile(String filePath) {
        if (filePath.endsWith(".pom")) {
            PomFile pomFile = new PomFile();
            if (pomFile.parse(filePath)) {
                pomFile.save();
            }
        }
    }

    void handlePrjFile(ProjectContext prjCtx, String name, String result) {
        String mainPkg = "/starter/" + prjCtx.getArtifactIdPkg() + "/";

        try {
            String artId = prjCtx.getArtifactId();
            String pathName = name.replace(MAIN_STARTER, artId + "-starter");
            int tmLen = JAVA_STARTER.length();
            File tmPath;

            if (name.startsWith(JAVA_STARTER)) {
                int pos = name.lastIndexOf("/");
                String fileName = name.substring(pos + 1);
                String midDir = name.substring(0, pos);
                String groupId = prjCtx.getGroupId().replace(".", "/");
                String tmDir = groupId + mainPkg;
                tmDir = prjCtx.getCurrentDir()
                        + JAVA_STARTER.replace(MAIN_STARTER, artId + "-starter")
                        + "/" + tmDir + midDir.substring(tmLen);
                tmPath = new File(tmDir);
                tmPath.mkdirs();
                if (fileName.equals(MAIN_JAVA_FILE)) {
                    tmPath = new File(tmDir + "/"
                            + StrUtil.firstUpper(artId) + "Starter" + fileName);
                } else {
                    tmPath = new File(tmDir + "/" + fileName);
                }
            } else {
                tmPath = new File(prjCtx.getCurrentDir() + pathName);
            }

            FileUtil.saveStrToFile(tmPath, prjCtx.handleContent(result)
                    .getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
